#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/wait.h>
#include<stdlib.h>
#include<string.h>
#include<errno.h>
#define SIZE 512
#define END '\0'
#define SEP " "
#define NUM 32
#define SkipPath(p) do{p+=(strlen(p)-1);while(*p != '/') --p;}while(0)
void Die()
{
  exit(1);
}
const char* GetUserName()
{
   const char* username = getenv("USER");
   if(username == NULL) return "None";
   return username;
}
const char* GetHostName()
{
  const char* hostname  = getenv("HOSTNAME");
  if(hostname == NULL)return "None";
  return hostname;
}
const char* GetCwd()
{
  char* cwd = getenv("PWD");  
  if(cwd == NULL)return "None";
  return cwd;
}
void MakeCommandLine()
{
   char line[SIZE];
   const char* username = GetUserName();
   const char* hostname = GetHostName();
   const char* Cwd  = GetCwd();
   SkipPath(Cwd);
   snprintf(line,SIZE,"[%s@%s %s@]> ",username,hostname,strlen(Cwd) == 1? "/" : Cwd+1);
   printf("%s",line);
   fflush(stdout);
}
int GetUserCommand(char command[],size_t n)
{  
  char* str = fgets(command,n,stdin);
  if(str == NULL) return -1;
  //小细节：清空回车键导致的usercommand的最后元素的位置被改成的'\n'
  command[strlen(command)-1] = END;
  return strlen(command);
}
const char*GetHome()
{
   const char* home = getenv("HOME");
   return home;
}
char* gArgv[NUM];
void SplitCommand(char command[],size_t n)
{
  (void)n;
   //使用strtok函数
   gArgv[0] = strtok(command,SEP);
   int i = 1;
   while((gArgv[i++] = strtok(NULL,SEP)));
}
void EexCuteCommand()
{
  pid_t id = fork();
  if(id < 0) Die();
  else if(id == 0)
  {
    //child
    //_程序替换
    execvp(gArgv[0],gArgv);
    exit(errno);
  }
  else 
  {
    //father 
    int status = 0;
    pid_t rid = waitpid(id,&status,0);
    (void)rid;
  }
}

char cwd[SIZE*2];
void Cd()
{
   const char* path = gArgv[1];
   if(path == NULL ) path = GetHome();
   chdir(path);
   char tmpspacce[SIZE*2];
   getcwd(tmpspacce,sizeof tmpspacce);
   snprintf(cwd,sizeof cwd,"PWD=%s",tmpspacce);
   putenv(cwd);

}
int checkBuild()
{
  int YES= 0;
  const char*cmd = gArgv[0];
  if(strcmp(cmd,"cd") == 0)
  {
     YES = 1;
     Cd();
  }
  return YES;
}
int main()
{
  int quit = 0;
  while(!quit)
  {
    //获取命令行
    MakeCommandLine();
    //获取指令字符串
    char usercommand[SIZE];
    int n = GetUserCommand(usercommand,sizeof usercommand);
    (void)n;
  
    //分割命令行字符串的分割
    SplitCommand(usercommand,sizeof usercommand);
    //检测是否是内建命令
    checkBuild();
    //执行命令
    EexCuteCommand();
    
  }
  return 0;
}

